import java.io.*;
import java.net.InetAddress;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.server.UnicastRemoteObject;
import java.util.Date;
import java.util.List;
import java.util.Properties;

/**
 *
 * @author Alejandro Figueroa
 */
public class AccesoRemoto extends UnicastRemoteObject implements ITanqueRemoto{

    // <editor-fold defaultstate="collapsed" desc="Variables">

    private int puerto = 0;
    private boolean alarma= false;
    private boolean alarmaQuemado = false;
    private int capacidadTanque = 0;
    private int capacidadMaxima = 50000;
    private String ip;
    private String url;
    private int puerto2;
    private ITanqueRemoto obj = null;
    private Loggers bitacora = new Loggers();
    private Pantalla ventana;
    private int litrosEnviar = 0;
    private int numeroPropio;
    private int numeroProximoTanque;

    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="Constructores">

    public AccesoRemoto() throws RemoteException
    {
        super();

        Properties props = new Properties();

        try
        {
            props.load(new FileInputStream("tanque.properties"));

            numeroPropio = Integer.parseInt(props.getProperty("numeroTanque"));
            numeroProximoTanque = Integer.parseInt(props.getProperty("tanqueProximo"));
            ip = props.getProperty("IPProximo");
            puerto = Integer.parseInt(props.getProperty("puertoProximoTanque"));
            puerto2 = Integer.parseInt(props.getProperty("puertoPropio"));
            url = "//" + ip + ":" + puerto + "/Tanque"+numeroProximoTanque;

        }catch (Exception e)
        {
            System.out.println("ERROR: no se pudo cargar el archivo de propiedades");
        }

        ventana = new Pantalla(this);
        ventana.setVisible(true);
    }

    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="Implementacion de ITanqueRemoto">

    /**
     * Metodo encargado de realizar la transferencia de los litros sobrantes
     * al otro tanque
     * @param litros: cantidad de litros a transferir
     * @param tanquesFull: en caso de que venga porque los tanques pasan su capacidad maxima
     * se envia aqui el numero de tanques de capacidad max ha sido sobrepasada
     */
    public void transferirLitros (int litros, int tanquesFull){

        try{

            obj = (ITanqueRemoto) Naming.lookup(url);
            obj.recibirPetroleo(litros,tanquesFull);

            bitacora.escribirBitacora("Litros: " + String.valueOf(litros) , "transferir", "Capacidad superior 70%");

        }catch (Exception e) {

            bitacora.escribirBitacora("Litros: " + String.valueOf(litros), "transferir", "Error al transferir");

        }

    }

    /**
     * Metodo encargado de Recibir la cantidad de litros de otro tanque
     * y de luego llamar al revisar tanques a ver que pasa
     * @param litrosRecibidos: litros que se quieren sumar al tanque
     * @param tanquesFull: en caso de que venga porque los tanques pasan su capacidad maxima
     * se envia aqui el numero de tanques de capacidad max ha sido sobrepasada
     */
    public void recibirPetroleo (int litrosRecibidos, int tanquesFull){

        this.revisarTanques(litrosRecibidos,tanquesFull);

    }

    /**
     * Metodo encargado de verificar si el tanque esta en capacidad normal
     * superando el 70 % o en capacidad maxima excedida
     * @param litrosAdquiridos: litros a sumar
     * @param tanquesFull: en caso de que venga porque los tanques pasan su capacidad maxima
     * se envia aqui el numero de tanques de capacidad max ha sido sobrepasada
     */
    public void revisarTanques (int litrosAdquiridos, int tanquesFull){

        String respuesta= "";

        Validaciones validar = new Validaciones();
        respuesta = validar.validarCapacidad(this.capacidadMaxima, this.capacidadTanque);

        if (respuesta.compareTo("nada") == 0){

            this.capacidadTanque= this.capacidadTanque + litrosAdquiridos;
            alarma= false;

            if ((alarmaQuemado == true) && (this.capacidadTanque <= this.capacidadMaxima*50/100)){
                alarmaQuemado = false;
            }

            ventana.imprimirVista("Entrada: normal \n");
            ventana.imprimirVista("Litros Actuales: " + String.valueOf(this.capacidadTanque) + "\n\n");
        }
        else{

            if (respuesta.compareTo("70") == 0){

                if (litrosAdquiridos != 0){

                    litrosEnviar = litrosAdquiridos*70/100;
                    alarma = true;

                    this.capacidadTanque= this.capacidadTanque + litrosAdquiridos - litrosEnviar;

                    ventana.imprimirVista("Entrada: mayor 70 \n");
                    ventana.imprimirVista("Litros Adquiridos: " + String.valueOf(litrosAdquiridos -litrosEnviar) + "\n");
                    ventana.imprimirVista("Litros Transferidos: " + String.valueOf(litrosEnviar) + "\n");
                    ventana.imprimirVista("Litros Actuales: " + String.valueOf(this.capacidadTanque) + "\n\n");

                    this.transferirLitros(litrosEnviar,0);

                }

            }
            else{

                //Cuando el tanque tiene capacidad maxima superada
                //Cuando respuesta = max

                alarmaQuemado = true;

                if (tanquesFull == 3){

                    this.llamadaFinalizar(tanquesFull);
                }
                else{

                    if (litrosAdquiridos != 0){

                        litrosEnviar = litrosAdquiridos*70/100;

                        this.capacidadTanque= this.capacidadTanque + litrosAdquiridos - litrosEnviar;

                        ventana.imprimirVista("Entrada: Capacidad Maxima Sobrepasa \n");
                        ventana.imprimirVista("Litros Adquiridos: " + String.valueOf(litrosAdquiridos -litrosEnviar)
                                + "\n");
                        ventana.imprimirVista("Litros Transferidos: " + String.valueOf(litrosEnviar) + "\n");
                        ventana.imprimirVista("Litros Actuales: " + String.valueOf(this.capacidadTanque) + "\n");
                        ventana.imprimirVista("Cantidad de Tanques Full: " + String.valueOf(tanquesFull + 1) + "\n\n");

                        this.transferirLitros(litrosEnviar, tanquesFull + 1);

                    }
                    else{

                        try{

                            obj = (ITanqueRemoto) Naming.lookup(url);
                            obj.revisarTanques(0,tanquesFull + 1);

                            ventana.imprimirVista("Entrada: Capacidad Maxima Sobrepasa con litros 0 \n");
                            ventana.imprimirVista("Cantidad de Tanques Full: " + String.valueOf(tanquesFull + 1) + "\n\n");

                            bitacora.escribirBitacora("Tanques: " + String.valueOf(tanquesFull) , "revisar",
                                    "Capacidad superior 70%");

                        }catch (Exception e) {

                            bitacora.escribirBitacora("Tanques: " + String.valueOf(tanquesFull), "revisar",
                                    "Error al transferir");

                        }

                    }

                }

            }

        }

    }

    /**
     * Metodo que se encarga de recibir la direccion de un archivo XML que contiene las entradas
     * de petroleo
     * @param dirArchivoXml: direccion del archivo xml
     */
    public void recibirEntradas (String dirArchivoXml){

        lecturaXML lectura = new lecturaXML();
        List entradas = lectura.runLectura(dirArchivoXml);
        XmlTanque objetoTanque = null;
        int litrosTotales = 0;

        if(entradas != null && entradas.size() > 0) {

            for(int i = 0 ; i < entradas.size();i++) {

                objetoTanque = (XmlTanque)entradas.get(i);
                litrosTotales = litrosTotales + objetoTanque.getLitrosEntrada();

            }

	}

        this.revisarTanques(litrosTotales, 0);

    }

    /**
     * Metodo encargado de terminar cada uno de los tanques pues se cumplio la condicion
     * @param tanquesTerminados: cantidad de tanques que faltan por cerrar
     */
    public void llamadaFinalizar (int tanquesTerminados){

        if (tanquesTerminados == 1){

                try {
                    this.finalize();
                } catch (Throwable ex) {
                    bitacora.escribirBitacora("Tanques Full: " + String.valueOf(tanquesTerminados) , "revisar",
                                "Capacidad superior a la maxima");
                }

        }
        else{

            try{

                obj = (ITanqueRemoto) Naming.lookup(url);
                obj.llamadaFinalizar(tanquesTerminados - 1);

                        bitacora.escribirBitacora("Tanques Full: " + String.valueOf(tanquesTerminados) , "revisar",
                                "Capacidad superior a la maxima");

                this.finalize();

            }catch (Throwable ex) {

                  bitacora.escribirBitacora("Finalizar Tanques: " + String.valueOf(tanquesTerminados) , "revisar",
                          "Error al Finalizar el Tanque");

            }

        }

    }

    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="Metodos Propios">

    /**
     * Metodo que levanta el Servidor para que sea accesible a los clientes
     * @return: regresa si el levantamiento fue exitoso o no
     */
    public boolean registrarServicio(){

        try
        {
            // crea el RMIRegistry en el puerto indicado
            LocateRegistry.createRegistry(puerto2);
            Naming.bind("//" + InetAddress.getLocalHost().getHostAddress() +":" + puerto2 + "/Tanque1", this);
            System.out.println("Servidor de Archivos ha sido iniciado exitosamente");
            return true;
         }
         catch (Exception e)
         {
            System.out.println("Error al iniciar servidor, causa: " + e.toString());
            return false;
         }
    }

    /**
     * Metodo de Prueba de imprecion de mensajes
     * @param mensaje: mensaje que se desea imprimir
     */
    public void metodoPrueba(String mensaje){
        ventana.imprimirVista(mensaje);
    }

    // </editor-fold>

}
